#include "HttpListener.h"
#include "GlobalConfig.h"
#include <stdexcept>
#include "Utils.h"


HttpListener::HttpListener()
:m_pServer(NULL)
,m_pConnection(NULL)
,m_InputStream("")
{
    //ctor
}

HttpListener::~HttpListener()
{
    //dtor
    Destroy();
}

void HttpListener::Init(const wxString& hostName, unsigned short port)
{
    m_listenAddress.Hostname(hostName);
    m_listenAddress.Service(port);

    if(NULL!=m_pServer) delete m_pServer;
    m_pServer = new wxSocketServer(m_listenAddress);
    m_pConnection = NULL;
}

void HttpListener::Destroy()
{
    delete m_pServer;
    m_pServer = NULL;
    delete m_pConnection;
    m_pConnection = NULL;
}

bool HttpListener::startListening(long timeoutSec)
{
    using std::runtime_error;

    try
    {
        if(NULL != m_pServer)
        {
            if(m_pServer->WaitForAccept(timeoutSec))
            {
                m_pConnection = m_pServer->Accept(false);
                if(NULL != m_pConnection)
                {
                    if(m_pConnection->IsOk() && m_pConnection->IsConnected())
                    {
                        return true;
                    }
                    else
                    {
                        throw runtime_error("Incoming connection lost when http listening");
                    }
                }
                else
                {
                    throw runtime_error("m_pConnection==NULL in startListening when http listening");
                }
            }
            else
            {
                throw runtime_error("Incoming connection time out when http listening");
            }
        }
        else
        {
            throw runtime_error("m_pServer==NULL");
        }
    }
    catch(runtime_error& e)
    {
        #ifdef HTTP_LOG
            LOGMAN.logError(e.what());
        #endif
        return false;
    }
}

bool HttpListener::readInputStream(wxString& resultStr)
{
    using std::runtime_error;

    try
    {
        if(m_pConnection!=NULL)
        {
            if(m_pConnection->IsData())
            {
                resultStr.Clear();

                char buff[HTTP_LISTEN_DATA_BUFFER_SIZE];
                memset(buff, 0, HTTP_LISTEN_DATA_BUFFER_SIZE);
                m_pConnection->Read(buff, HTTP_LISTEN_DATA_BUFFER_SIZE);
                //buff[HTTP_LISTEN_DATA_BUFFER_SIZE-1] = 0;     //avoid buffer overflow
                resultStr.Append(buff, strlen(buff));

                return true;
            }
            else
            {
                throw runtime_error("Incoming connection stream can't be read when http listening");
            }
        }
        else
        {
            throw runtime_error("m_pConnection==NULL in readInputStream when http listening");
        }
    }
    catch(runtime_error& e)
    {
        #ifdef HTTP_LOG
            LOGMAN.logError(e.what());
        #endif
        return false;
    }
}

bool HttpListener::listen(const wxString& hostName, unsigned short port, long timeoutSec)
{
    Init(hostName, port);

    using std::runtime_error;

    try
    {
        if(startListening(timeoutSec))
        {
            if(readInputStream(m_InputStream))
            {
                return true;
            }
            else
            {
                throw runtime_error("Read inputstream failed when http listening");
            }
        }
        else
        {
            throw runtime_error("Http listening stopped");
        }
    }
    catch(runtime_error& e)
    {
        #ifdef HTTP_LOG
            LOGMAN.logError(e.what());
        #endif
        return false;
    }
}
